/**
 * ProductionPlanningServiceImpl.java
 * @author
 * 作者 屈甲康 
 */
package org.jackysoft.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.hibernate.Session;
import org.jackysoft.entity.Department;
import org.jackysoft.entity.MonthPlanItemType;
import org.jackysoft.entity.MonthPlanning;
import org.jackysoft.entity.MonthPlanningItem;
import org.jackysoft.entity.MonthPlanningType;
import org.jackysoft.entity.PlanItemModifiedRecord;
import org.jackysoft.entity.Product;
import org.jackysoft.entity.ProductQuota;
import org.jackysoft.entity.Technics;
import org.jackysoft.entity.User;
import org.jackysoft.query.Order;
import org.jackysoft.query.Query;
import org.jackysoft.report.ReporterUtil;
import org.jackysoft.report.data.MonthPlanExporter;
import org.jackysoft.report.rows.PlanningItemRowWatcher;
import org.jackysoft.report.visitor.MonthPlanItemVisitor;
import org.jackysoft.service.AbstractStringIdServiceImpl;
import org.jackysoft.service.ArmMonthlyPlanService;
import org.jackysoft.service.DepartmentService;
import org.jackysoft.service.PlanItemModifiedRecordService;
import org.jackysoft.service.ProductService;
import org.jackysoft.service.TechnicsService;
import org.jackysoft.util.ExcelUtil;
import org.jackysoft.util.FileInfo;
import org.jackysoft.util.IOUtils;
import org.jackysoft.util.Page;
import org.jackysoft.util.RowWatcher;
import org.jackysoft.util.SOAOfficeUtil;
import org.jackysoft.util.SpringSecurityUtils;
import org.joda.time.DateTime;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Service
@Transactional
public class ArmMonthlyPlanServiceImpl extends
		AbstractStringIdServiceImpl<MonthPlanning> implements
		ArmMonthlyPlanService {
	/**
	 * 
	 */
	private static final long serialVersionUID = 5383312651523500835L;
	private static final Log logger = LogFactory
			.getLog(ArmMonthlyPlanServiceImpl.class);

	private ReporterUtil reportUtil;
	private PlanItemModifiedRecordService modifiedService;
	private TechnicsService techService;
	private ProductService productService;
	private MonthPlanItemVisitor itemVistor;
	private DepartmentService deptService;
	private int regenLevel;

	protected static final Map<String, String> fixedTecs = new HashMap<String, String>() {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		{
			put("表处", "冲压");
			put("落料", "冲压");
			put("切口", "机加");
			put("钻孔", "机加");
		}
	};

	public ArmMonthlyPlanServiceImpl() {
		this.type = MonthPlanning.class;
		
	}

	@PostConstruct
	public void init() {
		
		refresh();
		query = new Query();
		Order odr = new Order("createDate",Order.DESC);
		query.getOrders().add(odr);
	}

	@Override
	public void refresh() throws DataAccessException {
		// cache tenich
	}

	@Override
	@Transactional(readOnly = true)
	public MonthPlanning get(String id) throws DataAccessException {
		MonthPlanning p = super.get(id);
		afterGetAction(p);
		return p;
	}

	void afterGetAction(MonthPlanning plan) {
		for (MonthPlanningItem mi : plan.getDataItems()) {
			mi.setModifies(modifiedService.getsByHost(mi));
		}

	}

	@Override
	public void create(MonthPlanning bean) throws DataAccessException {
		if (bean.getCreateDate() == null)
			bean.setCreateDate(DateTime.now());
		bean.setPlanType(MonthPlanningType.Producted);
		create(getChildrenPlan(bean), bean.getCreateDate());
	}

	private void create(
			Map<String, Collection<MonthPlanningItem>> childrenPlan,
			DateTime createDate) {
		Collection<MonthPlanning> plans = Lists.newArrayList();
		User user = SpringSecurityUtils.getCurrentUser();

		for (Map.Entry<String, Collection<MonthPlanningItem>> mentry : childrenPlan
				.entrySet()) {
			MonthPlanning mp = new MonthPlanning();
			mp.setDraftable(false);
			mp.setMaker(user);
			mp.setPlanType(MonthPlanningType.Mixed);
			mp.setDepartment(new Department(mentry.getKey()));
			mp.setDataItems(mentry.getValue());
			mp.setCreateDate(createDate);
			beforeCreationAction(mp, createDate);
			plans.add(mp);
		}

		create(plans);

	}

	/**
	 * 扫描改动的产品改动
	 * */
	@Override
	public void update(MonthPlanning bean) throws DataAccessException {

		MonthPlanning plan = (MonthPlanning) getSession().merge(bean);
		Collection<PlanItemModifiedRecord> prs = Lists.newArrayList();
		for (MonthPlanningItem mp : plan.getDataItems()) {
			prs.addAll(scan4Increment(mp));
		}
		for (PlanItemModifiedRecord pr : prs) {
			getSession().save(pr);
		}

	}

	/**
	 * 创建计划指南: 每月计划只存在一份 根据部门显示产品
	 * */
	@Override
	public void create(Collection<MonthPlanning> beans)
			throws DataAccessException {
		super.create(beans);

	}

	void beforeCreationAction(MonthPlanning bean, DateTime createDate) {

		// TODO 处理月报完成数
		Map<String, Double> completeds = Maps.newHashMap();
		itemVistor.setItemValue(completeds);
		Collection<MonthPlanningItem> items = bean.getDataItems();
		for (MonthPlanningItem item : items) {
			itemVistor.visite(item);
		}

	}

	@Override
	public void update(Collection<MonthPlanning> beans)
			throws DataAccessException {
		super.update(beans);
	}

	/**
	 * 清理计划
	 * */
	void clean(int year, int month, int day) {
		String hql = "from "
				+ this.table()
				+ "  p where year(p.createDate)=:year and month(p.createDate)=:month and day(p.createDate)=:day";
		List list = getSession().createQuery(hql).setInteger("year", year)
				.setInteger("month", month).setInteger("day", day).list();
		super.remove(list);
	}

	/**
	 * 生成月半成品计划 本次生成的计划量是 截止本月还需要生产多少该产品
	 * 
	 * @param ds
	 *            计划项
	 * @return 部门=>计划项集合
	 **/
	private Map<String, Collection<MonthPlanningItem>> getChildrenPlan(
			MonthPlanning plan) {

		Collection<MonthPlanningItem> ds = plan.getDataItems();
		Map<String, Collection<MonthPlanningItem>> oms = Maps.newHashMap();
		DateTime date = plan.getCreateDate();
		String dstr = date.getYear() + "" + date.getMonthOfYear();
		long stamp = Long.parseLong(dstr);
		if (ds == null || ds.size() == 0)
			return oms;

		for (MonthPlanningItem motherItem : ds) {
			// 获取该主计划项所属的产品
			if (motherItem == null)
				continue;
			motherItem.setItemStamp(stamp);
			motherItem.setItemType(MonthPlanItemType.Proterozoic);
			recursionGeneratePlanItem(motherItem, oms);
			afterRecursionGeneration(motherItem, oms);
		}
		// 此项代表草稿计划所有计划项被分解到各个部门子计划中去，由于计划项已经被生成
		// 所以这个计划本身被当作草稿留存
		// oms.put(plan.getDepartment().getId(), ds);
		// 合并生成的半成品计划项
		return oms;
	}

	private Map<String, Collection<MonthPlanningItem>> getChildrenPlan(
			Collection<MonthPlanningItem> ds) {

		final Map<String, Collection<MonthPlanningItem>> oms = Maps
				.newHashMap();

		if (ds == null || ds.size() == 0)
			return oms;

		DateTime now = DateTime.now();
		String dstr = now.getYear() + "" + now.getMonthOfYear() + ""
				+ now.getDayOfMonth();
		long stamp = Long.parseLong(dstr);
		for (MonthPlanningItem motherItem : ds) {
			// 获取该主计划项所属的产品
			if (motherItem == null)
				continue;
			motherItem.setItemStamp(stamp);
			motherItem.setItemType(MonthPlanItemType.Proterozoic);
			recursionGeneratePlanItem(motherItem, oms);
			afterRecursionGeneration(motherItem, oms);

		}
		return oms;
	}

	/**
	 * 在生成或者导入计划时，把导入的成品自身也作为计划项加入集合
	 * */

	void afterRecursionGeneration(MonthPlanningItem motherItem,
			Map<String, Collection<MonthPlanningItem>> oms) {

		String code = motherItem.getOwner().getCode();
		Product motherOwner = productService.get(code);
		Iterator<Department> deptItr = motherOwner.getProviders().iterator();
		if (deptItr.hasNext()) {
			Department mdept = deptItr.next();
			Collection<MonthPlanningItem> mitems = oms.get(mdept.getId());
			if (mitems == null) {
				mitems = Lists.newArrayList();
				oms.put(mdept.getId(), mitems);
			}
			mitems.add(motherItem);

		}
	}

	/**
	 * 递归生成计划项
	 * 
	 * @param pdt
	 *            产品
	 * @param motherItem
	 *            父计划项
	 * @param oms
	 *            计划项容器
	 * */
	private void recursionGeneratePlanItem(MonthPlanningItem motherItem,
			Map<String, Collection<MonthPlanningItem>> oms) {
		logger.info("循环生成层级:" + regenLevel);
		if (regenLevel++ >= 5) {
			regenLevel = 0;
			return;
		}
		Product host = motherItem.getOwner();

		// logger.info("产品  " + host.getCode() + "正在生成");
		// 取得该产品所规定的定额
		Collection<ProductQuota> qs = productService.getsQuotas(host);

		for (ProductQuota pq : qs) {
			// 根据多部门生成各自计划
			Product pdt = pq.getOwner();
			// logger.info("\t部件 " + pdt.getCode() + "正在生成");
			Collection<ProductQuota> cqs = productService.getsQuotas(pdt);

			MonthPlanningItem tmother = null;

			Collection<Department> pdrs = pdt.getProviders();

			for (Department pdr : pdrs) {

				MonthPlanningItem tpi = new MonthPlanningItem();

				tpi.setHost(host);
				Double dx = motherItem.getValue();
				Product owner = pq.getOwner();
				tpi.setValue(pq.getConsume() * (dx == null ? 1D : dx));

				tpi.setRemark("\n" + motherItem.getRemark());
				tpi.setOwner(owner);
				tpi.setItemType(MonthPlanItemType.Generated);
				tpi.setItemStamp(motherItem.getItemStamp());

				Collection<MonthPlanningItem> pset = oms.get(pdr.getId());
				if (pset == null) {
					pset = Lists.newArrayList();
					oms.put(pdr.getId(), pset);
				}
				Technics ts = techService.get(pdr, owner);

				tpi.setTechnics(ts);
				if (ts != null) {
					String copDeptName = fixedTecs.get(ts.getName());
					
					Department dept = deptService.getByName(copDeptName);
					String copDeptId = dept.getId();
					Collection<MonthPlanningItem> copSet = oms.get(copDeptId);
					if (copSet == null) {
						copSet = Lists.newArrayList();
						oms.put(copDeptId, copSet);
					}
					copSet.add(tpi.clone());

				}
				pset.add(tpi);

				tmother = tpi;
			}
			if (cqs != null && !cqs.isEmpty()) {
				recursionGeneratePlanItem(tmother, oms);
			}
			// logger.info("\t部件 " + pdt.getCode() + "生成完毕!");
		}
	}

	@Resource
	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	@Override
	public Double valueToCurrent(int year, int month, String code)
			throws DataAccessException {
		if (year <= 2010 || month > 12)
			throw new IllegalArgumentException("参数 year :" + year + " month:"
					+ month + " 可能不合法");
		Double val = 0d;
		String hql = "from "
				+ table()
				+ " p where  p.planType=:ptype  and  year(p.createDate)=:year and month(p.createDate)<:month";
		Session s = getSession();
		List ls = s.createQuery(hql).setInteger("year", year)
				.setInteger("month", month)
				.setParameter("ptype", MonthPlanningType.Producted).list();
		Iterator itr = ls.iterator();
		while (itr.hasNext()) {
			MonthPlanning p = (MonthPlanning) itr.next();
			MonthPlanningItem exp = new MonthPlanningItem();
			exp.setOwner(productService.get(code));
			MonthPlanningItem tp = getReportUtil().findByCode(p.getDataItems(),
					exp);
			val += tp.getValue();
		}
		return val;
	}

	@Override
	public void importPlanning(int year, int month, int day)
			throws DataAccessException {
		// clean(year, month,day);
		byte[] content = SOAOfficeUtil.parseSOAOfficeStream();

		importPlanning(content, year, month, day);

	}

	/**
	 * 从文件导入计划,并根据定额关系生成部件计划
	 * 
	 * @param content
	 *            主计划Excel内容
	 * @param year
	 *            年份
	 * @param month
	 *            月份
	 * */
	void importPlanning(byte[] content, int year, int month, int day) {
		User user = SpringSecurityUtils.getCurrentUser();
        this.
        remove(year, month);  
		// 部门=>计划项集合
		Collection<MonthPlanningItem> mps = Lists.newArrayList();
		RowWatcher rw = new PlanningItemRowWatcher(mps, productService);
		ExcelUtil.parseForImport(content, rw);
		Map<String, Collection<MonthPlanningItem>> planMapper = getChildrenPlan(mps);
		DateTime createDate = DateTime.now().withDate(year, month, day);
		Collection<MonthPlanning> plist = Lists.newArrayList();
		for (Entry<String, Collection<MonthPlanningItem>> mentry : planMapper
				.entrySet()) {
			if (null == mentry.getKey())
				continue;
			MonthPlanning mp = new MonthPlanning();
			mp.setMaker(user);
			mp.setDepartment(new Department(mentry.getKey()));
			mp.setCreateDate(createDate);
			mp.setPlanType(MonthPlanningType.Mixed);
			mp.setDataItems(mentry.getValue());
			beforeCreationAction(mp, createDate);
			plist.add(mp);
			logger.info("已生成计划" + mp.getDepartment().getId());
		}
		logger.info("执行计划插入...");
		create(plist);
		logger.info("计划插入完成!");
	}

	@Override
	public void importPlanning(DateTime actionDate) throws DataAccessException {
		if (actionDate == null)
			actionDate = DateTime.now();
		importPlanning(actionDate.getYear(), actionDate.getMonthOfYear(),
				actionDate.getDayOfMonth());
	}

	@Override
	public void importPlanning(File plan, DateTime actionDate)
			throws DataAccessException {
		if (actionDate == null)
			actionDate = DateTime.now();
		byte[] content = IOUtils.toByteArray(plan);
		importPlanning(content, actionDate.getYear(),
				actionDate.getMonthOfYear(), actionDate.getDayOfMonth());

	}

	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Collection<MonthPlanning> find(int year, int month)
			throws DataAccessException {
		String hql = "from "
				+ table()
				+ " p where year(p.createDate)=:year and month(p.createDate)=:month";
		List list = query(hql).setInteger("year", year)
				.setInteger("month", month).list();
		return list;
	}

	@Override
	@SuppressWarnings({ "unchecked" })
	public Collection<MonthPlanning> find(int year, int month, Department dept)
			throws DataAccessException {
		String hql = this.FromCLause()
				+ " p where p.department=:dept and  year(p.createDate)=:year and month(p.createDate)=:month";
		List<MonthPlanning> list = query(hql).setInteger("year", year)
				.setInteger("month", month).setParameter("dept", dept).list();
		for (MonthPlanning plan : list)
			afterGetAction(plan);
		return list;
	}

	@Override
	public void remove(int year, int month) throws DataAccessException {
		Collection<MonthPlanning> mps = gets(year, month);
		if (mps.iterator().hasNext()) {
			remove(mps.iterator().next());
		}

	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
	public void remove(MonthPlanning t) throws DataAccessException {
		t = get(t.getId());
		Collection<PlanItemModifiedRecord> prs = Lists.newArrayList();
		for (MonthPlanningItem mi : t.getDataItems()) {
			prs.addAll(modifiedService.getsByHost(mi));
		}
		modifiedService.remove(prs);
		super.remove(t);
	}

	private void update(int year, int month, MonthPlanning old,
			MonthPlanning mtemp) throws DataAccessException {
		if (mtemp == null) {
			logger.error(String
					.format("MonthPlanning provided %s for year %d month %d not found! ",
							mtemp, new Integer(year), new Integer(month)));
			return;
		}

		if (old == null) {
			logger.error(String
					.format("MonthPlanning provided %s for year %d month %d not found! ",
							old, new Integer(year), new Integer(month)));
			return;
		}
		old.setOutputValue(mtemp.getOutputValue());
		old.setUpdateDate(mtemp.getUpdateDate());
		old.getDataItems().addAll(mtemp.getDataItems());

	}

	@Override
	public void update(int year, int month, MonthPlanning mtemp)
			throws DataAccessException {
		if (mtemp == null) {
			logger.warn(String
					.format("MonthPlanning provided %s for year %d month %d not found! ",
							mtemp, new Integer(year), new Integer(month)));
			return;
		}
		Collection<MonthPlanning> ps = gets(year, month);
		if (ps.iterator().hasNext())
			update(year, month, ps.iterator().next(), mtemp);
		else
			logger.warn("No plan with year " + year + " month " + month
					+ " can be updated!");

	}

	/**
	 * 修改业务描述: <dd>当计划项变动,计算变动增量(+/-) <dd>更新主计划中的数据值,增加量 <dd>更新子计划中的原值
	 * 
	 * @param mp
	 *            计划项
	 **/
	protected Collection<PlanItemModifiedRecord> scan4Increment(
			MonthPlanningItem mp) throws DataAccessException {
		if (mp == null || mp.getModifiedValue() == 0D)
			return Collections.emptyList();
		Collection<PlanItemModifiedRecord> prs = Lists.newArrayList();
		DateTime updateDate = DateTime.now();
		User user = SpringSecurityUtils.getCurrentUser();
		PlanItemModifiedRecord pr = new PlanItemModifiedRecord(mp, updateDate,
				mp.getModifiedValue(), user);
		prs.add(pr);
		Collection<MonthPlanningItem> children = getsChildrenItem(mp);
		for (MonthPlanningItem child : children) {
			Product parentPdt = mp.getOwner();
			Product childPdt = child.getOwner();
			ProductQuota pq = productService
					.calculateQuota(parentPdt, childPdt);
			PlanItemModifiedRecord pmr = new PlanItemModifiedRecord(child,
					updateDate, mp.getModifiedValue() * pq.getConsume(), user);
			prs.add(pmr);
		}
		return prs;
	}

	@Resource
	public void setModifiedService(PlanItemModifiedRecordService modifiedService) {
		this.modifiedService = modifiedService;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public Collection<MonthPlanningItem> getsChildrenItem(
			MonthPlanningItem mother) throws DataAccessException {
		Collection<ProductQuota> childquota = productService.getsQuotas(mother
				.getOwner());
		Collection<String> pdtIds = Lists.newArrayList();
		for (ProductQuota pqs : childquota)
			pdtIds.add(pqs.getOwner().getCode());
		if (pdtIds.isEmpty())
			return Collections.emptyList();
		String hql = String
				.format("from %s mp where mp.itemStamp=:stamp and  mp.owner.code in (:pdts)",
						MonthPlanningItem.class.getName());
		List list = getSession().createQuery(hql)
				.setLong("stamp", mother.getItemStamp())
				.setParameterList("pdts", pdtIds).list();
		return list;
	}

	@Resource
	public void setTechService(TechnicsService techService) {
		this.techService = techService;
	}

	@Override
	public Page query(Query qc, Integer pindex, Integer rows)
			throws DataAccessException {
		Page page = new Page();
		int start = (pindex + 1) * rows - rows;
		if (start < 0)
			start = 0;
		page.setPage(pindex);
		int total = qc == null ? count() : count(qc);
		page.setRecords(total);
		page.setOffset(rows);

		if (qc != null) {
			Department dept = new Department();
			dept.setId(qc.getFields().get(0).getValue());
			page.setRows(gets(start, rows, dept));
		} else {
			page.setRows(gets(start, rows));
		}
		return page;
	}

	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Collection<MonthPlanning> gets(int page, int rows, Department dept)
			throws DataAccessException {

		String hql = String
				.format("from %s p where p.department=:dept order by p.createDate desc",
						table());
		int start = page * rows;
		if (start < 0)
			start = 0;

		List list = query(hql).setParameter("dept", dept).setFirstResult(start)
				.setMaxResults(rows).list();
		return list;
	}

	@Override
	public FileInfo download(String id) throws Exception {
		MonthPlanning mp = get(id);
		MonthPlanExporter mpe = new MonthPlanExporter(mp);
		FileInfo fi = new FileInfo();
		fi.setTitle(mp.getDepartment().getName() + "-"
				+ mp.getCreateDate().toString("yyyy年MM月") + "-生产计划.xls");
		fi.setData(mpe.toExcel());
		fi.setFileType("xls");
		return fi;
	}

	@Resource
	public void setItemVistor(MonthPlanItemVisitor itemVistor) {
		this.itemVistor = itemVistor;
	}

	public ReporterUtil getReportUtil() {
		return reportUtil;
	}

	@Resource
	public void setReportUtil(ReporterUtil reportUtil) {
		this.reportUtil = reportUtil;
	}

	@Override
	public FileInfo download(DateTime actionDate)
			throws DataAccessException, IOException {
		Collection<MonthPlanning> plans = find(actionDate.getYear()
				,actionDate.getMonthOfYear(),actionDate.getDayOfMonth());
		Workbook wb = new HSSFWorkbook();
		CellStyle tstyle = wb.createCellStyle();
		tstyle.setFillBackgroundColor(IndexedColors.YELLOW.getIndex());

		Font font = wb.createFont();
		font.setFontHeightInPoints((short) 18);
		font.setFontName("Courier New");
		font.setBoldweight(Font.BOLDWEIGHT_BOLD);
		font.setColor(IndexedColors.ORANGE.getIndex());
		tstyle.setFont(font);

		CellStyle style = wb.createCellStyle();
		style.setFillBackgroundColor(IndexedColors.BLUE_GREY.getIndex());
		font = wb.createFont();
		font.setFontHeightInPoints((short) 14);
		font.setFontName("黑体");
		font.setColor(IndexedColors.BLUE.getIndex());
		style.setFont(font);

		for (MonthPlanning plan : plans) {
			String sname = plan.getDepartment().getName();
			logger.info("处理 " + sname);
			Sheet sheet = wb.createSheet(sname);
			Collection<MonthPlanningItem> items = plan.getProterozoic();
			int rownum = 0;
			Row row = sheet.createRow(rownum++);
			Cell title = row.createCell(0);
			title.setCellValue("成品计划");
			title.setCellStyle(tstyle);
			logger.info(items);
			for (MonthPlanningItem item : items) {
				row = sheet.createRow(rownum++);
				createCells(sheet, row, style, item);
			}

			row = sheet.createRow(rownum++);
			title = row.createCell(0);
			title.setCellValue("生成的半成品计划");
			title.setCellStyle(tstyle);
			Map<String, List<MonthPlanningItem>> planMap = plan.getGenerated();
			for (Map.Entry<String, List<MonthPlanningItem>> entry : planMap
					.entrySet()) {
				String key = entry.getKey();
				row = sheet.createRow(rownum++);
				Cell cell = row.createCell(0);
				cell.setCellStyle(tstyle);
				cell.setCellValue(key);

				items = entry.getValue();
				for (MonthPlanningItem item : items) {
					row = sheet.createRow(rownum++);
					createCells(sheet, row, style, item);
				}
			}

		}
		ByteArrayOutputStream bao = new ByteArrayOutputStream();
		wb.write(bao);
		FileInfo fi = new FileInfo();
		fi.setTitle(actionDate.toString("yyyy年MM月dd日计划")+".xls");
		fi.setFileType("xls");
		fi.setData(bao.toByteArray());
		return fi;
	}

	void createCells(Sheet sheet, Row row, CellStyle style,
			MonthPlanningItem item) {
		int c = 0;

		Cell cell = row.createCell(c++);
		cell.setCellValue(item.getOwner().getCode());
		cell.setCellStyle(style);
		cell = row.createCell(c++);
		cell.setCellValue(item.getOwner().getName());
		cell.setCellStyle(style);
		cell = row.createCell(c++);
		cell.setCellValue(item.getFinalValue());
		cell.setCellStyle(style);
		cell = row.createCell(c++);
		cell.setCellValue(item.getValidator().toString());
		cell.setCellStyle(style);
		cell = row.createCell(c++);
		cell.setCellValue(getTechnics(item.getTechnics()));
		cell.setCellStyle(style);
		cell = row.createCell(c++);
		cell.setCellValue(item.getRemark());
		cell.setCellStyle(style);
		for (int m = 0; m < 6; m++) {
			sheet.setColumnWidth(m, 30 * 256);
		}

	}

	String getTechnics(Technics t) {
		return t == null ? "" : t.getName();
	}

	@Override
	public Collection<MonthPlanning> find(int year, int month, int day)
			throws DataAccessException {
		String hql = "from "
				+ table()
				+ " p where year(p.createDate)=:year and month(p.createDate)=:month and day(p.createDate)=:day";
		List list = query(hql)
				.setInteger("year", year)
				.setInteger("month", month)
				.setInteger("day", day)
				.list();
		
		return list;
	}

	@Resource
	public void setDeptService(DepartmentService deptService) {
		this.deptService = deptService;
	}

}